﻿// 
//=====================================================================================
// Repository: https://gitee.com/putzone/fofasearch
//=====================================================================================
//
using FofaLib;
using OfficeOpenXml;
using System;
using System.Data;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FOFA搜索
{
    public partial class Form1 : Form
    {
        private delegate void FillDataDelegate(DataGridView dataGridView, FResult fResult);
        private static readonly string BaseDir = AppDomain.CurrentDomain.BaseDirectory;
        private static string EmailConfig = string.Empty;
        private static string ApiKeyConfig = string.Empty;
        private static string SearchKey = string.Empty;
        private static string LastSearchUrl = string.Empty;

        public Form1()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Text = "FOFA搜索[" + Assembly.GetExecutingAssembly().GetName().Version.ToString() + "]";
            linkLabel1.TabStop = false;

            AccountConfig account = Registry.Load();
            EmailConfig = account.Email;
            ApiKeyConfig = account.ApiKey;
            textBox1.Text = account.Email;
            textBox2.Text = account.ApiKey;
            textBox3.Text = account.Size;
            SearchKey = account.SearchKey;
            multiSelect1.CheckedText = account.Fields;

            KeyMapping keyMapping = new KeyMapping();
            foreach (string col in keyMapping.Header.Keys)
            {
                multiSelect1.AddItems(col);
            }

            NewTabPage();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Registry.Save(textBox1.Text, textBox2.Text, SearchKey, multiSelect1.CheckedText, textBox3.Text);
        }

        private void SearchButtonClick(object sender, EventArgs e)
        {
            TabPage thisTabPage = (TabPage)((Button)sender).Parent;
            string email = textBox1.Text;
            string apiKey = textBox2.Text;
            SearchKey = thisTabPage.Controls[1].Text;
            string sizeStr = textBox3.Text;
            string fields = multiSelect1.CheckedText;
            if (email != EmailConfig || apiKey != ApiKeyConfig)
            {
                Registry.Save(email, apiKey, SearchKey, fields, textBox3.Text);
                EmailConfig = email;
                ApiKeyConfig = apiKey;
            }
            if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(apiKey))
            {
                Warning("警告", "邮箱账号或API KEY有误");
                return;
            }
            if (string.IsNullOrEmpty(SearchKey))
            {
                Warning("警告", "搜索语法不能为空");
                return;
            }
            if (!int.TryParse(sizeStr, out int size))
            {
                size = 100;
                textBox3.Text = "100";
            }

            if (SearchKey.Length > 14)
            {
                thisTabPage.Text = SearchKey.Substring(0, 14);
            }
            else
            {
                thisTabPage.Text = SearchKey;
            }
            thisTabPage.ToolTipText = SearchKey;
            tabControl1.ItemSize = new Size(90, 18);
            DataGridView dataGridView1 = (DataGridView)thisTabPage.Controls[4];
            dataGridView1.DataSource = null;

            label5.Text = "正在执行中...";

            DisableUI(true);
            Task.Factory.StartNew(() =>
            {
                FofaClient fofaClient = new FofaClient()
                {
                    Email = email,
                    ApiKey = apiKey,
                    Fields = fields
                };
                FResult fResult = fofaClient.Search(SearchKey, size);

                if (fResult.Error)
                {
                    Warning("警告", fResult.ErrorMsg);
                    label5.Text = "";
                }
                else
                {
                    FillDataDelegate fillDataDelegate = new FillDataDelegate(FillData);
                    Invoke(fillDataDelegate, dataGridView1, fResult);
                }
                LastSearchUrl = fResult.SearchUrl;
                DisableUI(false);
            });
        }

        private void OutputButtonClick(object sender, EventArgs e)
        {
            if (tabControl1.TabCount == 0)
            {
                Warning("警告", "当前没有搜索结果");
                return;
            }
            string fileName = BaseDir + DateTime.UtcNow.AddHours(8).ToString("yyyyMMddHHmmss") + ".xlsx";
            try
            {
                ExcelPackage package;
                ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
                package = new ExcelPackage(new FileInfo(fileName));
                ExcelWorksheet ws = package.Workbook.Worksheets.Add("output");
                DataGridView dataGridView1 = (DataGridView)tabControl1.SelectedTab.Controls[4];

                if (dataGridView1.DataSource != null)
                {
                    DisableUI(true);
                    Task.Factory.StartNew(() =>
                    {
                        ws.Cells.LoadFromDataTable((DataTable)dataGridView1.DataSource, true);
                        for (int n = 1; n <= ws.Dimension.Columns; n++)
                        {
                            ws.Column(n).Width = 16;
                        }
                        ws.Cells[1, 1, 1, ws.Dimension.Columns].Style.Font.Bold = true;
                        ws.Cells[1, 1, 1, ws.Dimension.Columns].AutoFilter = true;
                        package.Save();
                        if (MessageBox.Show("导出成功，文件名为" + fileName + "，是否需要打开？", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
                        {
                            System.Diagnostics.Process.Start(fileName);
                        }
                        DisableUI(false);
                    });
                }
                else
                {
                    Warning("警告", "没有可以导出的数据");
                }
            }
            catch (Exception ex)
            {
                Warning("导出出错", ex.Message);
            }
        }

        private void NewTabPageButtonClick(object sender, EventArgs e)
        {
            NewTabPage();
        }

        private void LinkClick(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://gitee.com/putzone/fofasearch");
        }

        private void TabControl1_ControlRemoved(object sender, ControlEventArgs e)
        {
            if (tabControl1.TabCount > 1)
            {
                tabControl1.SelectTab(tabControl1.TabCount - 2);
            }
        }

        private void TabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tabControl1.TabCount != 0)
            {
                tabControl1.SelectedTab.Controls[1].Focus();
                AcceptButton = (Button)tabControl1.SelectedTab.Controls[2];
            }
        }

        private void NewTabPage()
        {
            Label newLabel = new Label()
            {
                Location = new Point(3, 7),
                Size = new Size(59, 12),
                Text = "搜索语法:"
            };
            TextBox newTextBox = new TextBox()
            {
                Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right,
                Location = new Point(62, 4),
                Size = new Size(598, 21),
                Text = SearchKey
            };
            Button newButton1 = new Button()
            {
                Anchor = AnchorStyles.Top | AnchorStyles.Right,
                Location = new Point(666, 3),
                Size = new Size(45, 23),
                Text = "搜索"
            };
            newButton1.Click += SearchButtonClick;
            Button newButton2 = new Button()
            {
                Anchor = AnchorStyles.Top | AnchorStyles.Right,
                Location = new Point(715, 3),
                Size = new Size(45, 23),
                Text = "关闭"
            };
            newButton2.Click += RemoveTabPage;

            DataGridViewCellStyle dataGridViewCellStyle7 = new DataGridViewCellStyle
            {
                BackColor = Color.WhiteSmoke
            };
            DataGridViewCellStyle dataGridViewCellStyle8 = new DataGridViewCellStyle
            {
                Alignment = DataGridViewContentAlignment.MiddleLeft,
                BackColor = SystemColors.Control,
                Font = new Font("宋体", 9F, FontStyle.Bold, GraphicsUnit.Point, 134),
                ForeColor = SystemColors.WindowText,
                SelectionBackColor = SystemColors.Highlight,
                SelectionForeColor = SystemColors.HighlightText,
                WrapMode = DataGridViewTriState.True
            };
            DataGridView newDataGridView = new DataGridView()
            {
                AllowUserToAddRows = false,
                AllowUserToDeleteRows = false,
                AlternatingRowsDefaultCellStyle = dataGridViewCellStyle7,
                Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right,
                BackgroundColor = Color.WhiteSmoke,
                ColumnHeadersDefaultCellStyle = dataGridViewCellStyle8,
                ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize,
                Location = new Point(0, 29),
                ReadOnly = true,
                RowHeadersWidth = 45,
                Size = new Size(764, 340),
            };
            newDataGridView.RowTemplate.Height = 23;
            newDataGridView.CellContextMenuStripNeeded += NewDataGridView_CellContextMenuStripNeeded;
            DoubleBuffered(newDataGridView, true);

            TabPage newTabPage = new TabPage()
            {
                UseVisualStyleBackColor = true,
                Location = new Point(4, 22),
                Padding = new Padding(3),
                Size = new Size(765, 369),
                Text = "新建搜索页面",
            };
            newTabPage.Controls.Add(newLabel);
            newTabPage.Controls.Add(newTextBox);
            newTabPage.Controls.Add(newButton1);
            newTabPage.Controls.Add(newButton2);
            newTabPage.Controls.Add(newDataGridView);
            tabControl1.TabPages.Add(newTabPage);
            tabControl1.SelectedTab = newTabPage;
            newTextBox.Focus();
            AcceptButton = newButton1;
        }

        private void NewDataGridView_CellContextMenuStripNeeded(object sender, DataGridViewCellContextMenuStripNeededEventArgs e)
        {
            if (e.ColumnIndex != -1 && e.RowIndex != -1)
            {
                DataGridView dgv = (DataGridView)sender;
                dgv.ClearSelection();
                dgv[e.ColumnIndex, e.RowIndex].Selected = true;
                contextMenuStrip1.Items[0].Visible = false;
                contextMenuStrip1.Items[5].Visible = false;
                if (dgv.Columns[e.ColumnIndex].Name == "IP")
                {
                    contextMenuStrip1.Items[5].Visible = true;
                }
                if (dgv.Columns[e.ColumnIndex].Name == "主机" && dgv.Columns.Contains("协议"))
                {
                    string value = dgv[dgv.Columns["协议"].Index, e.RowIndex].Value.ToString();
                    if(value == "http" || value == "https" || value == "")
                    {
                        contextMenuStrip1.Items[0].Visible = true;
                    }
                }
                e.ContextMenuStrip = contextMenuStrip1;
            }
        }

        private void ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem tsmi = (ToolStripMenuItem)sender;
            ContextMenuStrip cms = (ContextMenuStrip)tsmi.Owner;
            DataGridView dgv = (DataGridView)cms.SourceControl;
            string field = string.Empty;
            string value = dgv.SelectedCells[0].Value.ToString();
            KeyMapping keyMapping = new KeyMapping();
            foreach (string k in keyMapping.Header.Keys)
            {
                if (keyMapping.Header[k] == dgv.SelectedCells[0].OwningColumn.HeaderText)
                {
                    field = k;
                }
            }
            switch (field)
            {
                case "":
                    field = dgv.SelectedCells[0].OwningColumn.HeaderText;
                    break;
                case "lastupdatetime":
                    field = "after";
                    value = value.Substring(0, value.IndexOf(" "));
                    break;
                case "as_number":
                    field = "asn";
                    break;
                case "as_organization":
                    field = "org";
                    break;
            }
            TextBox textBox = (TextBox)dgv.Parent.Controls[1];
            textBox.Text = textBox.Text.Trim();
            textBox.Text = textBox.Text.Trim('&');
            textBox.Text = textBox.Text.Trim();
            if (tsmi.Name == "包含此项ToolStripMenuItem")
            {
                textBox.Text += string.Format(" && {0}=\"{1}\"", field, value);
            }
            else if (tsmi.Name == "等于此项ToolStripMenuItem")
            {
                textBox.Text += string.Format(" && {0}==\"{1}\"", field, value);
            }
            else if (tsmi.Name == "排除此项ToolStripMenuItem")
            {
                textBox.Text += string.Format(" && {0}!=\"{1}\"", field, value);
            }
            else if (tsmi.Name == "新建标签搜索此项ToolStripMenuItem")
            {
                NewTabPage();
                tabControl1.SelectedTab.Controls[1].Text = string.Format("{0}=\"{1}\"", field, value);
                SearchButtonClick(tabControl1.SelectedTab.Controls[2], null);
            }
            else if (tsmi.Name == "新建标签搜索C段ToolStripMenuItem")
            {
                NewTabPage();
                tabControl1.SelectedTab.Controls[1].Text = string.Format("{0}=\"{1}/24\"", field, value);
                SearchButtonClick(tabControl1.SelectedTab.Controls[2], null);
            }
            else if (tsmi.Name == "浏览器打开ToolStripMenuItem")
            {
                string protocol = dgv[dgv.Columns["协议"].Index, dgv.SelectedCells[0].RowIndex].Value.ToString();
                if (string.IsNullOrEmpty(protocol))
                {
                    if(value.IndexOf("http") == -1)
                    {
                        System.Diagnostics.Process.Start("http://" + value);
                    }
                    else
                    {
                        System.Diagnostics.Process.Start(value);
                    }
                }
                else
                {
                    System.Diagnostics.Process.Start(protocol + "://" + value);
                }
            }
        }

        private void label5_Click(object sender, EventArgs e)
        {
            Clipboard.SetText(LastSearchUrl);
        }

        private void RemoveTabPage(object sender, EventArgs e)
        {
            TabPage thisTabPage = (TabPage)((Button)sender).Parent;
            tabControl1.TabPages.Remove(thisTabPage);
            foreach (Control control in thisTabPage.Controls)
            {
                control.Dispose();
            }
            thisTabPage.Dispose();
            GC.Collect();
        }

        private void DisableUI(bool disable)
        {
            if (disable)
            {
                textBox1.Enabled = false;
                textBox2.Enabled = false;
                textBox3.Enabled = false;
                multiSelect1.Enabled = false;
                button1.Enabled = false;
                NewTabPageButton.Enabled = false;
                tabControl1.Enabled = false;
            }
            else
            {
                textBox1.Enabled = true;
                textBox2.Enabled = true;
                textBox3.Enabled = true;
                multiSelect1.Enabled = true;
                button1.Enabled = true;
                NewTabPageButton.Enabled = true;
                tabControl1.Enabled = true;
            }
        }

        private void FillData(DataGridView dataGridView1, FResult fResult)
        {
            dataGridView1.DataSource = fResult.ResultSet;
            label5.Text = "查询完毕，共" + fResult.Size.ToString() + "个结果，已读取" + fResult.ResultSet.Rows.Count.ToString() + "个结果";

        }

        private static new void DoubleBuffered(DataGridView dgv, bool setting)
        {
            Type dgvType = dgv.GetType();
            PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
            pi.SetValue(dgv, setting, null);
        }

        private void Warning(string title, string content)
        {
            MessageBox.Show(content, title, MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (tabControl1.TabPages.Count > 0 && e.KeyCode == Keys.W && e.Control)
            {
                RemoveTabPage(tabControl1.SelectedTab.Controls[3], null);
            }
        }
    }
}
